Kotlin

Coding Conventions

Swift

Naming rules

                  open class DeclarationProcessor { /*...*/ }
​
object EmptyDeclarationProcessor : DeclarationProcessor() { /*...*/ }
                
                    class DeclarationProcessor { /*...*/ }
​
let emptyDeclarationProcessor : DeclarationProcessor.shared()

                  

Function names

                  fun processDeclarations() { /*...*/ }
var declarationCount = 1
                
                    func processDeclarations() { /*...*/ }
var declarationCount = 1

                  
                  interface Foo { /*...*/ }
​
class FooImpl : Foo { /*...*/ }
​
fun Foo(): Foo { return FooImpl() }
                
                    protocol Foo { /*...*/ }

class FooImpl : Foo { /*...*/ }

func foo() -> Foo { return FooImpl() }

                  

Names for test methods

                  class MyTestCase {
     @Test fun `ensure everything works`() { /*...*/ }
     
     @Test fun ensureEverythingWorks_onAndroid() { /*...*/ }
}
                
                    class MyTestCase: XCTestCase {

    func testLogin() throws { /* */ }
}

                  

Property names

                  const val MAX_COUNT = 8
val USER_NAME_FIELD = "UserName"
                
Names of types and protocols are UpperCamelCase. Everything else is lowerCamelCase.
                  val mutableCollection: MutableSet<String> = HashSet()
                
                    var mutableCollection = Set<String>()

                  
                  val PersonComparator: Comparator<Person> = /*...*/
                
                    let personComparator: Comparator<Person> = /*...*/

                  

Names for backing properties

                  class C {
    private val _elementList = mutableListOf<Element>()
​
    val elementList: List<Element>
         get() = _elementList
}
                
                    class C {
    private var _elementList = [Int]()

    var elementList: [Int] {
        get { return _elementList }
    }
}

                  

Formatting

                  if (elements != null) {
    for (element in elements) {
        // ...
    }
}
                
                    if elements != nil {
    for element in elements! {
        // ...
    }
}

                  

Horizontal whitespace

                  class A(val x: Int)
​
fun foo(x: Int) { ... }
​
fun bar() {
    foo(1)
}
                
                    class A {
    A(x: Int) {
    }
}
​
func foo(x: Int) { ... }
​
func bar() {
    foo(x: 1)
}

                  

Colon

                  abstract class Foo<out T : Any> : IFoo {
    abstract fun foo(a: Int): T
}
​
class FooImpl : Foo() {
    constructor(x: String) : this(x) { /*...*/ }
    
    val x = object : IFoo { /*...*/ } 
}
                
                    protocol IFoo {}
class AImpl: IFoo { /*...*/ }

protocol Foo: IFoo {
    associatedtype T
    func foo(a: Int) -> T
}

class FooImpl: Foo {
    init(x: String) { /*...*/ }

    func foo(a: Int) -> String { /*...*/ }

    let x: IFoo = AImpl()
}

                  

Class header formatting

                  class Person(id: Int, name: String)
                
                    class Person {
    var id: Int = 0
    var name: String = ""
}

                  
                  class Person(
    id: Int,
    name: String,
    surname: String
) : Human(id, name) { /*...*/ }
                
                    class Human {
    var id: Int = 0
    var name: String = ""

    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

class Person: Human {
    var surname: String = ""

    init(id: Int, name: String, surname: String) {
        super.init(id: id, name: name)
    }
}

                  
                  class Person(
    id: Int,
    name: String,
    surname: String
) : Human(id, name),
    KotlinMaker { /*...*/ }
                
                    class Person: Human, KotlinMaker {
    var surname: String = ""

    init(id: Int, name: String, surname: String) {
        super.init(id: id, name: name)
    }

    /*...*/
}

                  
                  class MyFavouriteVeryLongClassHolder :
    MyLongHolder<MyFavouriteVeryLongClass>(),
    SomeOtherInterface,
    AndAnotherOne {
​
    fun foo() { /*...*/ }
}
                
                    class MyFavouriteVeryLongClassHolder:
    MyLongHolder,
    SomeOtherInterface,
    AndAnotherOne {
    ​   ​
    typealias Type = MyFavouriteVeryLongClass
    func foo() { /*...*/ }
}

                  
                  class MyFavouriteVeryLongClassHolder :
    MyLongHolder<MyFavouriteVeryLongClass>(),
    SomeOtherInterface,
    AndAnotherOne 
{
    fun foo() { /*...*/ }
}
                
                    class MyFavouriteVeryLongClassHolder:
    MyLongHolder,
    SomeOtherInterface,
    AndAnotherOne
{
    ​   ​
    typealias Type = MyFavouriteVeryLongClass
    func foo() { /*...*/ }
}

                  

Modifiers

                  public / protected / private / internal
expect / actual
final / open / abstract / sealed / const
external
override
lateinit
tailrec
vararg
suspend
inner
enum / annotation / fun // as a modifier in `fun interface`
companion
inline
infix
operator
data
                
                    open
public
internal
fileprivate
private

                  
                  @Named("Foo")
private val foo: Foo
                
                    @propertyWrapper
struct SomeWrapper { /*...*/ }

                  

Annotation formatting

                  @Target(AnnotationTarget.PROPERTY)
annotation class JsonExclude
                
                    @available(iOS 10.0, macOS 10.12, *)
class MyClass {
    // class definition
}

                  
                  @JsonExclude @JvmField
var x: String
                
                  @Test fun foo() { /*...*/ }
                
                    @objc func foo() { /*...*/ }

                  

File annotations

                  /** License, copyright and whatever */
@file:JvmName("FooBar")
​
package foo.bar
                

Function formatting

                  fun longMethodName(
    argument: ArgumentType = defaultValue,
    argument2: AnotherArgumentType,
): ReturnType {
    // body
}
                
                    func longMethodName(
    argument: ArgumentType = defaultValue,
    argument2: AnotherArgumentType,
): ReturnType {
    // body
}

                  
                  fun foo(): Int {     // bad
    return 1 
}
​
fun foo() = 1        // good
                
👏
                    func foo() -> Int {
    return 1
}
​


                  

Expression body formatting

                  fun f(x: String, y: String, z: String) =
    veryLongFunctionCallWithManyWords(andLongParametersToo(), x, y, z)
                
                    func f(x: String, y: String, z: String) {
    veryLongFunctionCallWithManyWords(andLongParametersToo(), x, y, z)
}

                  

Property formatting

                  val isEmpty: Boolean get() = size == 0
                
                    var isEmpty: Bool {
    get { size == 0 }
}

                  
                  val foo: String
    get() { /*...*/ }
                
                    var foo: String {
    get { /*...*/ }
}

                  
                  private val defaultCharset: Charset? =
    EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
                
                    private let defaultCharset: Charset? = {
    EncodingRegistry.getInstance().getDefaultCharsetForPropertiesFiles(file)
}()

                  

Formatting control flow statements

                  if (!component.isSyncing &&
    !hasAnyKotlinRuntimeInScope(module)
) {
    return createKotlinNotConfiguredPanel(module)
}
                
                    if (!component.isSyncing &&
    !hasAnyKotlinRuntimeInScope(module)
) {
    createKotlinNotConfiguredPanel(module)
}

                  
                  if (condition) {
    // body
} else {
    // else part
}
​
try {
    // body
} finally {
    // cleanup
}
                
                    if condition {
    // body
} else {
    // else part
}

defer {
    // cleanup
}

do {
    try foo()
} catch {
}

                  
                  private fun parsePropertyValue(propName: String, token: Token) {
    when (token) {
        is Token.ValueToken ->
            callback.visitValue(propName, token.value)
​
        Token.LBRACE -> { // ...
        }
    }
}
                
                    private func parsePropertyValue(propName: String, token: Token) {
    switch token {
    case .valueToken:
        callback.visitValue(propName, token.value)
    case .lbrance: // ...
    }
}

                  
                  when (foo) {
    true -> bar() // good
    false -> { baz() } // bad
}
                
                    if foo {
    bar()
}else {
    baz()
}

                  

Method call formatting

                  drawSquare(
    x = 10, y = 10,
    width = 100, height = 100,
    fill = true
)
                
                    drawSquare(
    x: 10, y: 10,
    width: 100, height: 100,
    fill: true
)

                  

Chained call wrapping

                  val anchor = owner
    ?.firstChild!!
    .siblings(forward = true)
    .dropWhile { it is PsiComment || it is PsiWhiteSpace }
                
                    let anchor = owner
    ?.firstChild!
    .siblings(forward: true)
    .dropWhile { $0 is PsiComment || $0 is PsiWhiteSpace }

                  

Lambda formatting

                  list.filter { it > 10 }
                
                    list.filter { $0 > 10 }

                  
                  fun foo() {
    ints.forEach lit@{
        // ...
    }
}
                
                  appendCommaSeparated(properties) { prop ->
    val propertyValue = prop.get(obj)  // ...
}
                
                    appendCommaSeparated(properties) { prop in
    let propertyValue = prop.get(obj)  // ...
}

                  
                  foo {
   context: Context,
   environment: Env
   ->
   context.configureEnv(environment)
}
                
                    foo { context, environment in
   context.configureEnv(environment)
}

                  

Trailing commas

                  class Person(
    val firstName: String,
    val lastName: String,
    val age: Int, // trailing comma
)
                
                    class Person {
    var firstName: String = ""
    var lastName: String = ""
    var age: Int = 0
}

                  

Enumerations

                  enum class Direction {
    NORTH,
    SOUTH,
    WEST,
    EAST, // trailing comma
}
                
                    enum Direction {
    case north
    case south
    case west
    case east
}

                  

Value arguments

                  fun shift(x: Int, y: Int) { /*...*/ }
​
shift(
    25,
    20, // trailing comma
)
​
val colors = listOf(
    "red",
    "green",
    "blue", // trailing comma
)
                
                    func shift(x: Int, y: Int) { /*...*/ }

shift(
    x: 25,
    y: 20
)

let colors = [
    "red",
    "green",
    "blue", // trailing comma
]

                  

Class properties and parameters

                  class Customer(
    val name: String,
    val lastName: String, // trailing comma
)
​
class Customer(
    val name: String,
    lastName: String, // trailing comma
)
                
                    class Customer {
    var name: String?
    var lastName: String?
}

                  

Function value parameters

                  fun powerOf(
    number: Int, 
    exponent: Int, // trailing comma
) { /*...*/ }
​
constructor(
    x: Comparable<Number>,
    y: Iterable<Number>, // trailing comma
) {}
​
fun print(
    vararg quantity: Int,
    description: String, // trailing comma
) {}
                
                    func powerOf(
    number: Int,
    exponent: Int
) { /*...*/ }

init(
    x: Comparable<Number>,
    y: Iterable<Number>
) {}

func print(
    quantity: Int...,
    description: String
) {}

                  

Parameters with optional type (including setters)

                  val sum: (Int, Int, Int) -> Int = fun(
    x,
    y,
    z, // trailing comma
): Int {
    return x + y + x
}
println(sum(8, 8, 8))
                
                    let sum: (Int, Int, Int) -> Int = { $0 + $1 + $2 }

print(sum(8, 8, 8))

                  

Indexing suffix

                  class Surface {
    operator fun get(x: Int, y: Int) = 2 * x + 4 * y - 10
}
fun getZValue(mySurface: Surface, xValue: Int, yValue: Int) =
    mySurface[
        xValue,
        yValue, // trailing comma
    ]
                
                    class Surface {
    subscript(x: Int, y: Int) -> Int {
        2 * x + 4 * y - 10
    }
}
func getZValue(mySurface: Surface, xValue: Int, yValue: Int) -> Int {
    mySurface[
        xValue,
        yValue
    ]
}

                  

Lambda parameters

                  fun main() {
    val x = {
            x: Comparable<Number>,
            y: Iterable<Number>, // trailing comma
        ->
        println("1")
    }
​
    println(x)
}
                
                    func main() {
    let x: (Comparable<Number>, Iterable<Number>) = { x, y in
        print("1")
    }
​
    print(x)
}

                  

when entry

                  fun isReferenceApplicable(myReference: KClass<*>) = when (myReference) {
    Comparable::class,
    Iterable::class,
    String::class, // trailing comma
        -> true
    else -> false
}
                

Collection literals (in annotations)

                  annotation class ApplicableFor(val services: Array<String>)
​
@ApplicableFor([
    "serializer",
    "balancer",
    "database",
    "inMemoryCache", // trailing comma
])
fun run() {}
                

Type arguments

                  fun <T1, T2> foo() {}
​
fun main() {
    foo<
            Comparable<Number>,
            Iterable<Number>, // trailing comma
            >()
}
                

Type parameters

                  class MyMap<
        MyKey,
        MyValue, // trailing comma
        > {}
                

Destructuring declarations

                  data class Car(val manufacturer: String, val model: String, val year: Int)
val myCar = Car("Tesla", "Y", 2019)
​
val (
    manufacturer,
    model,
    year, // trailing comma
) = myCar
​
val cars = listOf<Car>()
fun printMeanValue() {
    var meanValue: Int = 0
    for ((
        _,
        _,
        year, // trailing comma
    ) in cars) {
        meanValue += year
    }
    println(meanValue/cars.size)
}
printMeanValue()
                

Documentation comments

                  /**
 * This is a documentation comment
 * on multiple lines.
 */
                
                    /**
 * This is a documentation comment
 * on multiple lines.
 */

                  
                  /** This is a short documentation comment. */
                
                    /** This is a short documentation comment. */
                  
                  // Avoid doing this:
​
/**
 * Returns the absolute value of the given number.
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
fun abs(number: Int) { /*...*/ }
​
// Do this instead:
​
/**
 * Returns the absolute value of the given [number].
 */
fun abs(number: Int) { /*...*/ }
                

Unit

                  fun foo() { // ": Unit" is omitted here
​
}
                
                    func foo() { // ": Void" is omitted here
​
}

                  

String templates

                  println("$name has ${children.size} children")
                
                    print("\(name) has \(children.size) children")

                  

Immutability

                  // Bad: use of mutable collection type for value which will not be mutated
fun validateValue(actualValue: String, allowedValues: HashSet<String>) { ... }
​
// Good: immutable collection type used instead
fun validateValue(actualValue: String, allowedValues: Set<String>) { ... }
​
// Bad: arrayListOf() returns ArrayList<T>, which is a mutable collection type
val allowedValues = arrayListOf("a", "b", "c")
​
// Good: listOf() returns List<T>
val allowedValues = listOf("a", "b", "c")
                
                    func validateValue(actualValue: String, allowedValues: Set<String>) { ... }
​
let allowedValues = ["a", "b", "c"]

                  

Default parameter values

                  // Bad
fun foo() = foo("a")
fun foo(a: String) { /*...*/ }
​
// Good
fun foo(a: String = "a") { /*...*/ }
                
                    // Bad
func foo() {
    foo(a: "a")
}
func foo(a: String) { /*...*/ }
​
// Good
func foo(a: String = "a") { /*...*/ }

                  

Type aliases

                  typealias MouseClickHandler = (Any, MouseEvent) -> Unit
typealias PersonIndex = Map<String, Person>
                
                    typealias MouseClickHandler = (Any, MouseEvent) -> Void
typealias PersonIndex = Map<String, Person>

                  

Named arguments

                  drawSquare(x = 10, y = 10, width = 100, height = 100, fill = true)
                
                    drawSquare(x: 10, y: 10, width: 100, height: 100, fill: true)

                  

Using conditional statements

                  return if (x) foo() else bar()
​
return when(x) {
    0 -> "zero"
    else -> "nonzero"
}
                
                    return x ? foo() : bar()
​
switch x {
case 0:
    return "zero"
default:
    return "nonzero"
}

                  
                  if (x)
    return foo()
else
    return bar()
    
when(x) {
    0 -> return "zero"
    else -> return "nonzero"
}
                
                    if x {
    return foo()
}else {
    return bar()
}

switch x {
case 0:
    return "zero"
default:
    return "nonzero"
}

                  

if versus when

                  when (x) {
    null -> // ...
    else -> // ...
}
                
                    switch x {
case nil: // ...
default: // ...
}

                  

Loops on ranges

                  for (i in 0..n - 1) { /*...*/ }  // bad
for (i in 0 until n) { /*...*/ }  // good
                
                    for i in 0...n-1 { /*...*/ }  // bad
for i in 0..<n) { /*...*/ }  // good

                  

Using strings

                  assertEquals(
    """
    Foo
    Bar
    """.trimIndent(), 
    value
)
​
val a = """if(a > 1) {
          |    return a
          |}""".trimMargin()
                
                    assert("""
    Foo
    Bar
    """ == "Foo\nBar")

let a = """
        if(a > 1) {
            return a
        }
        """

                  

Factory functions

                  class Point(val x: Double, val y: Double) {
    companion object {
        fun fromPolar(angle: Double, radius: Double) = Point(...)
    }
}
                
                    class Point {
    let x, y: Double = 0

    static func fromPolar(angle: Double, radius: Double) {
        Point(...)
    }
}

                  

Platform types

                  fun apiCall(): String = MyJavaApi.getProperty("name")
                
                  class Person {
    val name: String = MyJavaApi.getProperty("name")
}
                
                  fun main() {
    val name = MyJavaApi.getProperty("name")
    println(name)
}